﻿using H.Utils.DataStruct;
using HMaker.Events;
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace HMaker.Controls
{
    /// <summary>
    /// 表示一个通用的美化下拉选择框(使用ListView进行封装)
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class CommonListBox<T> : ListView where T : class
    {
        /// <summary>
        /// 缓冲池
        /// </summary>
        private readonly CommonPool<ListViewItem> _Pool = new CommonPool<ListViewItem>() { MaxCount = 300 };

        /// <summary>
        /// 哈希表
        /// </summary>
        private readonly WeakHashMap<T, ListViewItem> _HashMap = new WeakHashMap<T, ListViewItem>();


        /// <summary>
        /// 初始化列表函数
        /// </summary>
        protected abstract void InitList();

        /// <summary>
        /// 将一个对象转换为对应的ListViewItem,以便进行关联
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        protected abstract ListViewItem RenderItem(ListViewItem lvi, T obj);

        /// <summary>
        /// 当当前选择的组件发生改变时,发射此事件
        /// </summary>
        public event EventHandler<SelectItemArgs<T>> SelectObjectChanged;

        /// <summary>
        /// 当前正在操作的数据
        /// </summary>
        public ListViewItem CurLVI { get; private set; } = null;

        /// <summary>
        /// 获取当前正在操作的对象
        /// </summary>
        public T CurObject => CurLVI?.Tag as T;

        /// <summary>
        /// 初始化一个新的控件
        /// </summary>
        protected CommonListBox() : base()
        {
            View = View.Tile;
            FullRowSelect = true;
            InitList();
        }

        /// <summary>
        /// 生成一个ListViewItem(针对组件内部实现进行一定的调整)
        /// </summary>
        /// <param name="item">要显示的对象</param>
        /// <returns>返回一个显示某个数据的对象</returns>
        protected ListViewItem MakeLVI(T item)
        {
            ListViewItem lvi = _Pool.Malloc();
            lvi = RenderItem(lvi, item);
            lvi.Tag = item;
            _HashMap.Add(item, lvi);
            return lvi;
        }

        /// <summary>
        /// 刷新整个列表的数据
        /// </summary>
        public void ResetList(IEnumerable<T> objs)
        {
            BeginUpdate();
            foreach (ListViewItem lvi in Items)
            {
                _Pool.Free(lvi);
                _HashMap.Remove(lvi.Tag as T);
            }
            Items.Clear();
            if (objs != null)
            {
                foreach (T obj in objs)
                {
                    Items.Add(MakeLVI(obj));
                }
            }
            EndUpdate();
        }

        /// <summary>
        /// 插入一个数据
        /// </summary>
        /// <param name="index"></param>
        /// <param name="obj"></param>
        public void InsertItem(int index, T obj)
        {
            Items.Insert(index, MakeLVI(obj));
        }

        /// <summary>
        /// 新增一个数据
        /// </summary>
        /// <param name="obj"></param>
        public void AddItem(T obj)
        {
            Items.Add(MakeLVI(obj));
        }

        /// <summary>
        /// 移除当前选中的数据
        /// </summary>
        public void RemoveItem(T obj)
        {
            ListViewItem lvi = _HashMap[obj];
            Items.Remove(lvi);
        }

        /// <summary>
        /// 当鼠标右键按下时,弹出浮动菜单
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseDown(MouseEventArgs e)
        {
            ListViewItem lvi = GetItemAt(e.X, e.Y);

            if (CurLVI != lvi)
            {
                CurLVI = lvi;
                SelectObjectChanged?.Invoke(this, new SelectItemArgs<T>(lvi?.Tag as T, lvi));
            }
            base.OnMouseDown(e);
        }

        //protected override void OnContextMenuStripChanged(EventArgs e)
        //{
        //    if (ContextMenuStrip != null)
        //    {
        //        ContextMenuStrip.Opening -= ContextMenuStrip_Opening;
        //    }
        //    base.OnContextMenuStripChanged(e);
        //    if (ContextMenuStrip != null)
        //    {
        //        ContextMenuStrip.Opening += ContextMenuStrip_Opening;
        //    }
        //}

       // private void ContextMenuStrip_Opening(object sender, System.ComponentModel.CancelEventArgs e)
       // {
       //if ()
       // }
    }
}
